package com.baofu.paycore.biz.engine.generator.impl;

import com.baofu.account.service.facade.enums.FreezeTypeEnum;
import com.baofu.paycore.biz.engine.command.Command;
import com.baofu.paycore.biz.engine.command.impl.*;
import com.baofu.paycore.biz.engine.generator.CommandGenerator;
import com.baofu.paycore.common.enums.FundTypeEnum;
import com.baofu.paycore.common.exception.PayCoreServiceException;
import com.baofu.paycore.common.exception.ServiceErrorCode;
import com.baofu.paycore.common.utils.Constant;
import com.baofu.paycore.common.utils.DateUtil;
import com.baofu.paycore.manager.model.PayBaseBO;
import com.baofu.paycore.manager.model.withdraw.WithdrawBO;
import com.baofu.paycore.manager.model.withdraw.WithdrawBankBO;
import com.baofu.paycore.manager.model.withdraw.WithdrawFundBO;
import com.baofu.paycore.service.facade.enums.RequestSystemEnum;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * 提现指令生成
 *
 * <p>
 *  1.生成提现指令
 * </p>
 * User: xin deng  Date: 16/6/3 ProjectName: paycore Version: 1.0
 */
@Slf4j
@Service
public class WithdrawCommandGenerator implements CommandGenerator{

    /**
     * 生成提现指令
     *
     * @param payBaseBO   订单模型
     * @return            命令列表
     */
    @Override
    public List<Command> generatorCommands(PayBaseBO payBaseBO) {

        List<Command> list = Lists.newArrayList();
        WithdrawBO withdrawBO = (WithdrawBO) payBaseBO;
        //冻结单
        AccFreezeCommand accFreezeCommand = new AccFreezeCommand();
        assembleAccFreeze(withdrawBO, accFreezeCommand);
        list.add(accFreezeCommand);
        //提现银行单
        BankTransferCommand bankTransferCommand = new BankTransferCommand();
        assembleBankTransfer(withdrawBO, bankTransferCommand);
        list.add(bankTransferCommand);
        //解冻提现
        AccUnFreezeWithdrawCommand withdrawCommand = new AccUnFreezeWithdrawCommand();
        assembleAccWithdraw(withdrawBO, withdrawCommand);
        list.add(withdrawCommand);
        //提现转账手续费单
        AccUnFreezeTransferCommand transferCommand = assembleUnFreezeTransfer(withdrawBO);
        if (transferCommand != null){
            list.add(transferCommand);
        }
        return list;
    }

    /**
     * 组装手续费解冻转账指令
     *
     * @param withdrawBO    提现参数
     * @return              解冻转账指令
     */
    private AccUnFreezeTransferCommand assembleUnFreezeTransfer(WithdrawBO withdrawBO) {
        List<WithdrawFundBO> list = withdrawBO.getWithdrawFundBO();
        if (list.size() < 3) {
            return null;
        }
        WithdrawFundBO withdrawFundBO = withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(),
                FundTypeEnum.FEE.getCode());
        AccUnFreezeTransferCommand transferCommand = new AccUnFreezeTransferCommand();
        transferCommand.setTradeLogId(withdrawBO.getTradeLogId());
        transferCommand.setRequestSystem(RequestSystemEnum.PAYCORE.getCode());
        transferCommand.setAmount(withdrawFundBO.getReqAccAmt());
        transferCommand.setFreezeType(FreezeTypeEnum.DRAW.getCode());
        transferCommand.setRequestNo(withdrawFundBO.getFundDetailNo());
        transferCommand.setBizType(withdrawBO.getBizType());
        transferCommand.setSubBizType(withdrawBO.getSubBizType());
        transferCommand.setCcy(withdrawBO.getCcy());
        transferCommand.setEventNo(withdrawFundBO.getEventNo());
        transferCommand.setFundDetailNo(withdrawFundBO.getFundDetailNo());
        transferCommand.setPayerAccNo(withdrawFundBO.getBizFeeAccount());
        transferCommand.setSyncPayeeFlag(Boolean.TRUE);
        transferCommand.setOperator(withdrawBO.getOperator());
        transferCommand.setRequestDate(new Date());
        transferCommand.setFreezeReqNo(withdrawFundBO.getUnfreezeNo());

        return transferCommand;
    }

    /**
     * 组装账务冻结指令
     *
     * @param withdrawBO    提现参数
     * @param command       冻结指令
     */
    private void assembleAccFreeze(WithdrawBO withdrawBO, AccFreezeCommand command) {
        WithdrawFundBO withdrawFundBO = withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(),
                FundTypeEnum.WITHDRAW_FREEZE.getCode());
        command.setAmount(withdrawFundBO.getReqAccAmt());
        command.setBizType(withdrawBO.getBizType());
        command.setSubBizType(withdrawBO.getSubBizType());
        command.setCcy(withdrawFundBO.getCcy());
        command.setFundDetailNo(withdrawFundBO.getFundDetailNo());
        command.setOperator(withdrawBO.getOperator());
        command.setRequestDate(new Date());
        command.setRequestNo(withdrawFundBO.getFundDetailNo());
        command.setRequestSystem(RequestSystemEnum.PAYCORE.getCode());
        command.setAccountNo(withdrawBO.getAccountNo());
        command.setFreezeType(FreezeTypeEnum.DRAW.getCode());
        command.setExpiryDate(DateUtil.plusDays(Constant.DAY));
        command.setTradeLogId(withdrawBO.getTradeLogId());
        command.setServiceCode(withdrawBO.getServiceCode());
    }

    /**
     * 组装账户提现指令
     *
     * @param withdrawBO  提现参数
     */
    private void assembleAccWithdraw(WithdrawBO withdrawBO, AccUnFreezeWithdrawCommand accWithdrawCommand){

        WithdrawFundBO withdrawFundBO = withdrawBO.getWithdrawFund(withdrawBO.getWithdrawFundBO(),
                FundTypeEnum.UNFREEZE_WITHDRAW.getCode());
        if (withdrawFundBO == null){
            log.error("组装账户提现指令 withdrawBO为空");
            throw new PayCoreServiceException(ServiceErrorCode.WITHDRAW_FUND_INFO_NULL);
        }
        accWithdrawCommand.setRequestNo(withdrawFundBO.getFundDetailNo());
        accWithdrawCommand.setRequestSystem(RequestSystemEnum.PAYCORE.getCode());
        accWithdrawCommand.setRequestDate(new Date());
        accWithdrawCommand.setCcy(withdrawFundBO.getCcy());
        accWithdrawCommand.setAmount(withdrawFundBO.getReqAccAmt());
        accWithdrawCommand.setBizType(withdrawBO.getBizType());
        accWithdrawCommand.setSubBizType(withdrawBO.getSubBizType());
        accWithdrawCommand.setEventNo(withdrawFundBO.getEventNo());
        accWithdrawCommand.setPayerAccNo(withdrawFundBO.getAccountNo());
        accWithdrawCommand.setSyncPayeeFlag(Boolean.TRUE);
        accWithdrawCommand.setOperator(withdrawBO.getOperator());
        accWithdrawCommand.setFundDetailNo(withdrawFundBO.getFundDetailNo());
        accWithdrawCommand.setFreezeType(FreezeTypeEnum.DRAW.getCode());
        accWithdrawCommand.setTradeLogId(withdrawBO.getTradeLogId());
        accWithdrawCommand.setFreezeReqNo(withdrawFundBO.getUnfreezeNo());
    }

    /**
     * 组装银行转账指令
     *
     * @param withdrawBO  提现参数
     */
    private void assembleBankTransfer(WithdrawBO withdrawBO, BankTransferCommand command){
        WithdrawBankBO withdrawBankBO = withdrawBO.getWithdrawBankBO();
        if (null == withdrawBankBO){
            log.error("组装银行转账指令 withdrawBankBO为空");
            throw new PayCoreServiceException(ServiceErrorCode.WITHDRAW_BANK_INFO_NULL);
        }
        command.setRequestOrderNo(withdrawBankBO.getFundDetailNo());
        command.setBizDate(new Date());
        command.setAmt(withdrawBankBO.getAmt());
        command.setCcy(withdrawBankBO.getCcy());
        command.setRequestChannel(withdrawBO.getRequestChannel());
        command.setRequestSystem(withdrawBO.getRequestSystem());
        command.setContractNo(withdrawBO.getContractNo());
        command.setPayeeAccNo(withdrawBO.getAccountNo());
        command.setBizType(withdrawBO.getBizType());
        command.setSubBizType(withdrawBO.getSubBizType());
        command.setPayTool(withdrawBankBO.getPayToolType());
        command.setSubPayTool(withdrawBankBO.getPayToolSubType());
        command.setBankCode(withdrawBankBO.getBankCode());
        command.setAgreeRelId(withdrawBankBO.getAgreeRelId());
        command.setAgreementNo(withdrawBankBO.getAgreementNo());
        command.setTraceLogId(withdrawBO.getTradeLogId());
        command.setFundDetailNo(withdrawBankBO.getFundDetailNo());
        command.setPayNo(withdrawBankBO.getPayNo());
        command.setOperator(withdrawBO.getOperator());
    }
}
